package br.requisiteworks.controller;

import java.util.Arrays;
import java.util.List;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import br.requisiteworks.modelo.Funcionario;
import br.requisiteworks.modelo.service.FuncionarioService;
import br.requisiteworks.seguranca.modelo.UsuarioLogado;
import br.requisiteworks.util.persistencia.ErroBancoDados;
import br.requisiteworks.util.persistencia.ResultadoVazio;

/**
 * Implementacao de um controller que controla as operacoes relacionadas ao
 * modulo de {@link Funcionario}
 */
@Controller
@Secured( { "ROLE_GERENTE", "ROLE_ADMINISTRADOR" })
@RequestMapping("/funcionario")
public class FuncionarioController {

    @Autowired
    private FuncionarioService funcionarioService;

    private static final Funcionario VAZIO = new Funcionario();

    @RequestMapping("/pesquisar.do")
    public List<Funcionario> pesquisar(ModelMap model) {
	try {
	    return this.funcionarioService.listarFuncionarios();
	} catch (ResultadoVazio e) {
	    model.addAttribute("erro", e.getMessage());
	    return null;
	}
    }

    @RequestMapping(value = "/pesquisar.do", method = RequestMethod.POST)
    public List<Funcionario> pesquisarFuncionario(
	    @RequestParam("q") String query, ModelMap model) {

	if (query.matches("\\d+")) {
	    try {
		return Arrays.asList(this.funcionarioService
			.carregarFuncionario(Integer.parseInt(query)));
	    } catch (ResultadoVazio e) {
		model.addAttribute("erro", e.getMessage());
		return null;
	    } catch (NumberFormatException e) {
		// Nao deve ocorre devido a expressao regular
		return null;
	    }
	} else {
	    try {
		return this.funcionarioService.procuraNome(query.trim());
	    } catch (ResultadoVazio e) {
		model.addAttribute("erro", e.getMessage());
		return null;
	    }
	}

    }

    @RequestMapping(value = "/util/pesquisar.do", method = RequestMethod.GET)
    public void pesquisar() {
    }

    @RequestMapping(value = "/util/pesquisar.do", method = RequestMethod.POST)
    public List<Funcionario> pesquisar(@RequestParam("q") String query,
	    ModelMap model) {

	if (query.matches("\\d+")) {
	    try {
		return Arrays.asList(this.funcionarioService
			.carregarFuncionario(Integer.parseInt(query)));
	    } catch (ResultadoVazio e) {
		model.addAttribute("erro", e.getMessage());
		return null;
	    } catch (NumberFormatException e) {
		// Nao deve ocorre devido a expressao regular
		return null;
	    }
	} else {
	    try {
		return this.funcionarioService.procuraNome(query.trim());
	    } catch (ResultadoVazio e) {
		model.addAttribute("erro", e.getMessage());
		return null;
	    }
	}
    }

    @RequestMapping(value = "/{numero}/detalhes.do", method = RequestMethod.GET)
    public String atualizar(@PathVariable("numero") Integer numero,
	    ModelMap model) throws ResultadoVazio {
	model.addAttribute("funcionario", this.funcionarioService
		.carregarFuncionario(numero));
	return "funcionario/detalhes";
    }

    @RequestMapping(value = "/atualizar.do", method = RequestMethod.POST)
    public String atualizar(@Valid Funcionario novoFuncionario,
	    BindingResult result, ModelMap model) {

	if (result.hasErrors()) {
	    return null;
	}

	try {
	    Funcionario funcionario = this.funcionarioService
		    .carregarFuncionario(novoFuncionario.getNumero());

	    funcionario.setNome(novoFuncionario.getNome());
	    funcionario.setTelefone(novoFuncionario.getTelefone());
	    funcionario.setEmail(novoFuncionario.getEmail());
	    funcionario.setUsuarioRegistro(UsuarioLogado.getUsername());

	    this.funcionarioService.atualizarFuncionario(funcionario);
	} catch (ErroBancoDados e) {
	    model.addAttribute("erro", e.getMessage());
	}

	return "redirect:pesquisar.do";
    }

    @RequestMapping(value = "/deletar.do", method = RequestMethod.GET)
    public String deletar(@RequestParam("numero") Integer numero, ModelMap model) {
	try {
	    Funcionario funcionario = this.funcionarioService
		    .carregarFuncionario(numero);
	    this.funcionarioService.deletaFuncionario(funcionario);
	} catch (ErroBancoDados e) {
	    model.addAttribute("erro", e.getMessage());
	}

	return "redirect:pesquisar.do";
    }

    @RequestMapping(value = "/adicionar.do", method = RequestMethod.GET)
    public Funcionario adicionar() {
	return VAZIO;
    }

    @RequestMapping(value = "/adicionar.do", method = RequestMethod.POST)
    public String adicionar(@Valid Funcionario funcionario,
	    BindingResult result, ModelMap model) {

	if (result.hasErrors()) {
	    return null;
	}
	funcionario.setUsuarioRegistro(UsuarioLogado.getUsername());

	try {
	    this.funcionarioService.salvarFuncionario(funcionario);
	} catch (ErroBancoDados e) {
	    model.addAttribute("erro", e.getMessage());
	}

	return "redirect:pesquisar.do";
    }

}
